package com.engine.salary.service.impl;

import com.engine.common.util.ServiceUtil;
import com.engine.core.impl.Service;
import com.engine.salary.config.SalaryElogConfig;
import com.engine.hrmelog.entity.dto.LoggerContext;
import com.engine.salary.constant.TaxDeclarationDataIndexConstant;
import com.engine.salary.entity.taxagent.po.TaxAgentPO;
import com.engine.salary.entity.taxdeclaration.dto.TaxDeclarationAnnualListDTO;
import com.engine.salary.entity.taxdeclaration.dto.TaxDeclarationLaborListDTO;
import com.engine.salary.entity.taxdeclaration.dto.TaxDeclarationWageListDTO;
import com.engine.salary.entity.taxdeclaration.param.TaxDeclarationDetailListQueryParam;
import com.engine.salary.entity.taxdeclaration.po.TaxDeclarationPO;
import com.engine.salary.enums.OperateTypeEnum;
import com.engine.salary.enums.salarysob.IncomeCategoryEnum;
import com.engine.salary.mapper.taxdeclaration.TaxDeclarationDetailMapper;
import com.engine.salary.service.TaxAgentService;
import com.engine.salary.service.TaxDeclarationDetailService;
import com.engine.salary.service.TaxDeclarationExcelService;
import com.engine.salary.service.TaxDeclarationService;
import com.engine.salary.util.JsonUtil;
import com.engine.salary.util.SalaryDateUtil;
import com.engine.salary.util.SalaryI18nUtil;
import com.engine.salary.util.db.MapperProxyFactory;
import com.engine.salary.util.excel.ExcelUtil;
import com.engine.salary.util.page.PageInfo;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import weaver.hrm.User;

import java.math.BigDecimal;
import java.util.*;

/**
 * 个税申报表导出
 * <p>Copyright: Copyright (c) 2022</p>
 * <p>Company: 泛微软件</p>
 *
 * @author qiantao
 * @version 1.0
 **/
@Slf4j
public class TaxDeclarationExcelServiceImpl extends Service implements TaxDeclarationExcelService {

    private TaxDeclarationDetailService getTaxDeclarationDetailService(User user) {
        return ServiceUtil.getService(TaxDeclarationDetailServiceImpl.class, user);
    }
    private TaxDeclarationDetailMapper getTaxDeclarationDetailMapper() {
        return MapperProxyFactory.getProxy(TaxDeclarationDetailMapper.class);
    }
    private TaxDeclarationService getTaxDeclarationService(User user) {
        return ServiceUtil.getService(TaxDeclarationServiceImpl.class, user);
    }

    private TaxAgentService getTaxAgentService(User user) {
        return ServiceUtil.getService(TaxAgentServiceImpl.class, user);
    }



    @Override
    public XSSFWorkbook exportTaxDeclaration(Long taxDeclarationId) {
        // 1.工作簿名称
        String sheetName = SalaryI18nUtil.getI18nLabel(85368, "个税申报表");


        TaxDeclarationPO taxDeclarationPO = getTaxDeclarationService(user).getById(taxDeclarationId);
        // 查询当前个税申报表一共有多少人员
        int count = getTaxDeclarationDetailMapper().countEmployeeId(taxDeclarationId);
        // 以1000个人员一页，一共有多少页
        int totalPages = (count % 1000 == 0) ? (count / 1000) : (count / 1000 + 1); //总页数
        // excel导出的数据
        List<List<Object>> rows = Lists.newArrayListWithExpectedSize(count);
        List<Object> headerList = Lists.newArrayList();
        List<String> dataIndexList = Lists.newArrayList();
        List<String> NumberCode = Arrays.asList(TaxDeclarationDataIndexConstant.INCOME, TaxDeclarationDataIndexConstant.TAX_FREE_INCOME,
                TaxDeclarationDataIndexConstant.ENDOWMENT_INSURANCE, TaxDeclarationDataIndexConstant.MEDICAL_INSURANCE, TaxDeclarationDataIndexConstant.UNEMPLOYMENT_INSURANCE,
                TaxDeclarationDataIndexConstant.HOUSING_PROVIDENT_FUND, TaxDeclarationDataIndexConstant.ADD_UP_CHILD_EDUCATION, TaxDeclarationDataIndexConstant.ADD_UP_CONTINUING_EDUCATION,
                TaxDeclarationDataIndexConstant.ADD_UP_HOUSING_LOAN_INTEREST, TaxDeclarationDataIndexConstant.ADD_UP_HOUSING_RENT, TaxDeclarationDataIndexConstant.ADD_UP_SUPPORT_ELDERLY,
                TaxDeclarationDataIndexConstant.ADD_UP_ILLNESS_MEDICAL, TaxDeclarationDataIndexConstant.ADD_UP_INFANT_CARE, TaxDeclarationDataIndexConstant.ADD_UP_PRIVATE_PENSION,
                TaxDeclarationDataIndexConstant.ANNUITY, TaxDeclarationDataIndexConstant.COMMERCIAL_HEALTH_INSURANCE, TaxDeclarationDataIndexConstant.TAX_DEFERRED_ENDOWMENT_INSURANCE,
                TaxDeclarationDataIndexConstant.OTHER, TaxDeclarationDataIndexConstant.ALLOWED_DONATION, TaxDeclarationDataIndexConstant.TAX_DEDUCTION,
                TaxDeclarationDataIndexConstant.LABOR_INCOME, TaxDeclarationDataIndexConstant.LABOR_TAX_FREE_INCOME, TaxDeclarationDataIndexConstant.ANNUAL_INCOME,
                TaxDeclarationDataIndexConstant.ANNUAL_TAX_FREE_INCOME, TaxDeclarationDataIndexConstant.ANNUAL_OTHER, TaxDeclarationDataIndexConstant.ANNUAL_DONATE_TAX,
                TaxDeclarationDataIndexConstant.ANNUAL_TAX_SAVINGS);
        if (Objects.equals(taxDeclarationPO.getIncomeCategory(), IncomeCategoryEnum.WAGES_AND_SALARIES.getValue())) {
            // 解析表头
            ExcelUtil.parseHeader(TaxDeclarationWageListDTO.class, headerList, dataIndexList);
            rows.add(headerList);
            for (int i = 0; i < totalPages; i++) {
                TaxDeclarationDetailListQueryParam queryParam = new TaxDeclarationDetailListQueryParam();
                queryParam.setTaxDeclarationId(taxDeclarationId);
                queryParam.setCurrent(i+1);
                queryParam.setPageSize(1000);
                PageInfo<TaxDeclarationWageListDTO> dtoPage = getTaxDeclarationDetailService(user).listDtoPageByParam4Wage(queryParam);
                List<TaxDeclarationWageListDTO> list = dtoPage.getList();
                for (TaxDeclarationWageListDTO taxDeclarationWageListDTO : list) {
                    List<Object> row = Lists.newArrayListWithExpectedSize(dataIndexList.size());
                    Map<String, Object> map = JsonUtil.parseMap(taxDeclarationWageListDTO, Object.class);
                    for (String dataIndex : dataIndexList) {
                        try {
                            if (NumberCode.contains(dataIndex)) {
                                row.add(new BigDecimal(map.get(dataIndex).toString()));
                            } else {
                                row.add(map.get(dataIndex));
                            }
                        } catch (Exception e) {
                            row.add(map.get(dataIndex));
                        }
                    }
                    rows.add(row);
                }
            }
        }
        if (Objects.equals(taxDeclarationPO.getIncomeCategory(), IncomeCategoryEnum.REMUNERATION_FOR_LABOR.getValue())) {
            // 解析表头
            ExcelUtil.parseHeader(TaxDeclarationLaborListDTO.class, headerList, dataIndexList);
            rows.add(headerList);
            for (int i = 0; i < totalPages; i++) {
                TaxDeclarationDetailListQueryParam queryParam = new TaxDeclarationDetailListQueryParam();
                queryParam.setTaxDeclarationId(taxDeclarationId);
                queryParam.setCurrent(i);
                queryParam.setPageSize(1000);
                PageInfo<TaxDeclarationLaborListDTO> dtoPage = getTaxDeclarationDetailService(user).listDtoPageByParam4Labor(queryParam);
                List<TaxDeclarationLaborListDTO> list = dtoPage.getList();
                for (TaxDeclarationLaborListDTO taxDeclarationLaborListDTO : list) {
                    List<Object> row = Lists.newArrayListWithExpectedSize(dataIndexList.size());
                    Map<String, Object> map = JsonUtil.parseMap(taxDeclarationLaborListDTO, Object.class);
                    for (String dataIndex : dataIndexList) {
                        try {
                            if (NumberCode.contains(dataIndex)) {
                                row.add(new BigDecimal(map.get(dataIndex).toString()));
                            } else {
                                row.add(map.get(dataIndex));
                            }
                        } catch (Exception e) {
                            row.add(map.get(dataIndex));
                        }
                    }
                    rows.add(row);
                }
            }
        }

        if (Objects.equals(taxDeclarationPO.getIncomeCategory(), IncomeCategoryEnum.ONETIME_ANNUAL_BONUS.getValue())) {
            // 解析表头
            ExcelUtil.parseHeader(TaxDeclarationAnnualListDTO.class, headerList, dataIndexList);
            rows.add(headerList);
            for (int i = 0; i < totalPages; i++) {
                TaxDeclarationDetailListQueryParam queryParam = new TaxDeclarationDetailListQueryParam();
                queryParam.setTaxDeclarationId(taxDeclarationId);
                queryParam.setCurrent(i);
                queryParam.setPageSize(1000);
                PageInfo<TaxDeclarationAnnualListDTO> dtoPage = getTaxDeclarationDetailService(user).listDtoPageByParam4Annual(queryParam);
                List<TaxDeclarationAnnualListDTO> list = dtoPage.getList();
                for (TaxDeclarationAnnualListDTO taxDeclarationLaborListDTO : list) {
                    List<Object> row = Lists.newArrayListWithExpectedSize(dataIndexList.size());
                    Map<String, Object> map = JsonUtil.parseMap(taxDeclarationLaborListDTO, Object.class);
                    for (String dataIndex : dataIndexList) {
                        try {
                            if (NumberCode.contains(dataIndex)) {
                                row.add(new BigDecimal(map.get(dataIndex).toString()));
                            } else {
                                row.add(map.get(dataIndex));
                            }
                        } catch (Exception e) {
                            row.add(map.get(dataIndex));
                        }
                    }
                    rows.add(row);
                }
            }
        }

        // 查询个税扣缴义务人名称
        String bar = "_";
        TaxAgentPO taxAgentPO = getTaxAgentService(user).getById(taxDeclarationPO.getTaxAgentId());
        String targetName = SalaryDateUtil.getFormatYearMonth(taxDeclarationPO.getSalaryMonth())  + bar + taxAgentPO.getName() + bar + IncomeCategoryEnum.parseByValue(taxDeclarationPO.getIncomeCategory()).getDefaultLabel();
        // 记录日志
        LoggerContext<TaxDeclarationPO> loggerContext = new LoggerContext<>();
        loggerContext.setUser(user);
        loggerContext.setTargetId(taxDeclarationId.toString());
        loggerContext.setTargetName(targetName);
        loggerContext.setOperateType(OperateTypeEnum.EXCEL_EXPORT.getValue());
        loggerContext.setOperateTypeName(SalaryI18nUtil.getI18nLabel( 0, "导出个税申报表"));
        loggerContext.setOperatedesc(SalaryI18nUtil.getI18nLabel( 0, "导出个税申报表"));
        SalaryElogConfig.taxDeclarationLoggerTemplate.write(loggerContext);
        return ExcelUtil.genWorkbookV2(rows, sheetName);
    }

}
